package com.yunkeji.config.timer;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedissonLockExecutor;
import com.yunkeji.api.user.mapper.ApiAppUserMapper;
import com.yunkeji.common.constant.CacheConstants;
import com.yunkeji.common.enums.app.EnableEnum;
import com.yunkeji.common.utils.redis.RedisUtils;
import com.yunkeji.dao.domain.AppUserVip;
import com.yunkeji.dao.mapper.AppUserVipMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Date;
import java.util.List;

/**
 * 会员过期删除定时器-每天零点过期当天需要被过期的账号,发进去redis队列
 *
 * @author 老张
 */
@Component
@EnableScheduling
@Slf4j
@AllArgsConstructor
public class MemberExpireTimer {

    private final ApiAppUserMapper apiAppUserMapper;
    private final LockTemplate lockTemplate;
    private final AppUserVipMapper appUserVipMapper;

    @Scheduled(fixedRate = 5 * 60 * 1000)
    @Profile("test")
    public void delAccountTest() {
        expire();
    }

    //    @Scheduled(cron = "1 * * * * ?")
    //    @Profile("dev")
    public void delAccountDev() {
        expire();
    }

    @Scheduled(cron = "0 0 1 * * ?")
    @Profile("prod")
    public void delAccountProd() {
        expire();
    }

    /** 删除昨天的账号-补偿 */
    private void expireYestoday() {
        DateTime yesterday = DateUtil.yesterday();
        // 普通会员
        List<AppUserVip> vipCommon =
                appUserVipMapper.selectExpireCommonVip(
                        DateUtil.beginOfDay(yesterday), DateUtil.endOfDay(yesterday));
        // 专属会员
        List<AppUserVip> vipExclusive =
                appUserVipMapper.selectExpireExclusiveVip(
                        DateUtil.beginOfDay(yesterday), DateUtil.endOfDay(yesterday));

        log.info("会员过期删除定时器-补偿-普通会员:{}", vipCommon.size());
        log.info("会员过期删除定时器-补偿-专属会员:{}", vipExclusive.size());
        if (CollectionUtil.isNotEmpty(vipCommon)) {
            vipCommon.forEach(item -> item.setCommonVipFlag(EnableEnum.NO.getCode()));
            appUserVipMapper.updateBatchById(vipCommon);
        }

        if (CollectionUtil.isNotEmpty(vipExclusive)) {
            vipExclusive.forEach(item -> item.setExclusiveVipFlag(EnableEnum.NO.getCode()));
            appUserVipMapper.updateBatchById(vipExclusive);
        }
    }

    /** 删除当天的账号 */
    private void expire() {
        final LockInfo lockInfo =
                lockTemplate.lock(
                        CacheConstants.LOCK_MEMBER_EXPIRE_TIMER,
                        30000L,
                        5000L,
                        RedissonLockExecutor.class);
        if (null == lockInfo) {
            throw new RuntimeException("业务处理中,请稍后再试");
        }
        try {

            // 补偿昨天
            expireYestoday();

            Date currentDate = new Date();
            // 普通会员
            List<AppUserVip> vipCommon =
                    appUserVipMapper.selectExpireCommonVip(
                            DateUtil.beginOfDay(currentDate), DateUtil.endOfDay(currentDate));
            // 专属会员
            List<AppUserVip> vipExclusive =
                    appUserVipMapper.selectExpireExclusiveVip(
                            DateUtil.beginOfDay(currentDate), DateUtil.endOfDay(currentDate));
            log.info("会员过期删除定时器-定时-普通会员:{}", vipCommon.size());
            log.info("会员过期删除定时器-定时-专属会员:{}", vipExclusive.size());
            vipCommon.forEach(
                    item -> {
                        Object cacheObject =
                                RedisUtils.getCacheObject(
                                        CacheConstants.MEMBER_COMMON_EXPIRE + item.getId());
                        if (cacheObject == null) {
                            long l =
                                    DateUtil.between(
                                            currentDate,
                                            item.getCommonVipExpireTime(),
                                            DateUnit.SECOND);
                            RedisUtils.setCacheObject(
                                    CacheConstants.MEMBER_COMMON_EXPIRE + item.getId(),
                                    item.getId(),
                                    Duration.ofSeconds(l));
                        }
                    });
            vipExclusive.forEach(
                    item -> {
                        Object cacheObject =
                                RedisUtils.getCacheObject(
                                        CacheConstants.MEMBER_EXCLUSIVE_EXPIRE + item.getId());
                        if (cacheObject == null) {
                            long l =
                                    DateUtil.between(
                                            currentDate,
                                            item.getExclusiveVipExpireTime(),
                                            DateUnit.SECOND);
                            RedisUtils.setCacheObject(
                                    CacheConstants.MEMBER_EXCLUSIVE_EXPIRE + item.getId(),
                                    item.getId(),
                                    Duration.ofSeconds(l));
                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放锁
            lockTemplate.releaseLock(lockInfo);
        }
    }
}
